home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Graphics / SPD / Sources / readnff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-11  |  12.4 KB  |  507 lines  |  [TEXT/R*ch]

  1. /*
  2.  * ReadNFF.c - Simple NFF file importer.  Uses lib to output to
  3.  * many different raytracer formats.
  4.  *
  5.  * Author:  Eduard [esp] Schwan
  6.  *
  7.  * input file parameter...
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <math.h>
  12. #include <string.h>    /* strchr */
  13. #include <stdlib.h>    /* atoi */
  14. #include "def.h"
  15. #include "drv.h"    /* display_close() */
  16. #include "lib.h"
  17.  
  18. /* These may be read from the command line */
  19. static int raytracer_format = OUTPUT_RT_DEFAULT;
  20. static int output_format    = OUTPUT_CURVES;
  21.  
  22.  
  23. /*----------------------------------------------------------------------
  24. Handle an error
  25. ----------------------------------------------------------------------*/
  26. static void
  27. show_error(s)
  28. char    * s;
  29. {
  30.     SysBeep(1);
  31.     lib_output_comment("### ERROR! ###\n");
  32.     lib_output_comment(s);
  33.     lib_close();
  34. }
  35.  
  36. /*----------------------------------------------------------------------
  37. Comment.  Description:
  38.     "#" [ string ]
  39.  
  40. Format:
  41.     # [ string ]
  42.  
  43.     As soon as a "#" character is detected, the rest of the line is considered
  44.     a comment.
  45. ----------------------------------------------------------------------*/
  46. static void
  47. do_comment(fp)
  48. FILE *fp;
  49. {
  50.     char    *cp;
  51.     char    comment[256];
  52.  
  53.     fgets(comment, 255, fp);
  54.     /* strip out newline */
  55.     cp = (char*)strchr(comment, '\n');
  56.     if (cp != NULL)
  57.         *cp = '\0';
  58.     lib_output_comment(comment);
  59. }
  60.  
  61.  
  62. /*----------------------------------------------------------------------
  63. Viewpoint location.  Description:
  64.     "v"
  65.     "from" Fx Fy Fz
  66.     "at" Ax Ay Az
  67.     "up" Ux Uy Uz
  68.     "angle" angle
  69.     "hither" hither
  70.     "resolution" xres yres
  71.  
  72. Format:
  73.  
  74.     v
  75.     from %g %g %g
  76.     at %g %g %g
  77.     up %g %g %g
  78.     angle %g
  79.     hither %g
  80.     resolution %d %d
  81.  
  82. The parameters are:
  83.  
  84.     From:  the eye location in XYZ.
  85.     At:    a position to be at the center of the image, in XYZ world
  86.        coordinates.  A.k.a. "lookat".
  87.     Up:    a vector defining which direction is up, as an XYZ vector.
  88.     Angle: in degrees, defined as from the center of top pixel row to
  89.        bottom pixel row and left column to right column.
  90.     Resolution: in pixels, in x and in y.
  91.  
  92.   Note that no assumptions are made about normalizing the data (e.g. the
  93.   from-at distance does not have to be 1).  Also, vectors are not
  94.   required to be perpendicular to each other.
  95.  
  96.   For all databases some viewing parameters are always the same:
  97.     Yon is "at infinity."
  98.     Aspect ratio is 1.0.
  99.  
  100.   A view entity must be defined before any objects are defined (this
  101.   requirement is so that NFF files can be used by hidden surface machines).
  102. ----------------------------------------------------------------------*/
  103. static void
  104. do_view(fp)
  105. FILE *fp;
  106. {
  107.     float    x,y,z;
  108.     COORD3 from;
  109.     COORD3 at;
  110.     COORD3 up;
  111.     float fov_angle;
  112.     float aspect_ratio;
  113.     float hither;
  114.     int resx;
  115.     int resy;
  116.  
  117.     if (fscanf(fp, " from %f %f %f", &x, &y, &z) != 3)
  118.         goto fmterr;
  119.     SET_COORD3(from, x,y,z);
  120.  
  121.     if (fscanf(fp, " at %f %f %f", &x, &y, &z) != 3)
  122.         goto fmterr;
  123.     SET_COORD3(at, x,y,z);
  124.  
  125.     if (fscanf(fp, " up %f %f %f", &x, &y, &z) != 3)
  126.         goto fmterr;
  127.     SET_COORD3(up, x,y,z);
  128.  
  129.     if (fscanf(fp, " angle %f", &fov_angle) != 1)
  130.         goto fmterr;
  131.  
  132.     fscanf(fp, " hither %f", &hither);
  133.  
  134.     aspect_ratio = 1.0;
  135.  
  136.     fscanf(fp, " resolution %d %d", &resx, &resy);
  137.  
  138.     lib_output_viewpoint(from, at, up,
  139.                   fov_angle, aspect_ratio,
  140.                   hither, resx, resy);
  141.     return;
  142. fmterr:
  143.     show_error("NFF view syntax error");
  144.     exit(1);
  145. }
  146.  
  147.  
  148. /*----------------------------------------------------------------------
  149. Positional light.  A light is defined by XYZ position.  Description:
  150.     "l" X Y Z
  151.  
  152. Format:
  153.     l %g %g %g
  154.  
  155.     All light entities must be defined before any objects are defined (this
  156.     requirement is so that NFF files can be used by hidden surface machines).
  157.     Lights have a non-zero intensity of no particular value [this definition
  158.     may change soon, with the addition of an intensity and/or color].
  159. ----------------------------------------------------------------------*/
  160. static void
  161. do_light(fp)
  162. FILE *fp;
  163. {
  164.     float    x, y, z;
  165.     COORD4 acenter;
  166.  
  167.    if (fscanf(fp, "%f %f %f",&x, &y, &z) != 3) {
  168.     show_error("Light source syntax error");
  169.     exit(1);
  170.     }
  171.  
  172.     SET_COORD4(acenter,x,y,z,0.0); /* intensity=0 */
  173.  
  174.     lib_output_light(acenter);
  175. }
  176.  
  177.  
  178. /*----------------------------------------------------------------------
  179. Background color.  A color is simply RGB with values between 0 and 1:
  180.     "b" R G B
  181.  
  182. Format:
  183.     b %g %g %g
  184.  
  185.     If no background color is set, assume RGB = {0,0,0}.
  186. ----------------------------------------------------------------------*/
  187. static void
  188. do_background(fp)
  189. FILE *fp;
  190. {
  191.     float    r, g, b;
  192.     COORD3 acolor;
  193.  
  194.    if (fscanf(fp, "%f %f %f",&r, &g, &b) != 3) {
  195.     show_error("background color syntax error");
  196.     exit(1);
  197.     }
  198.     SET_COORD3(acolor,r,g,b);
  199.  
  200.     lib_output_background_color(acolor);
  201. }
  202.  
  203.  
  204. /*----------------------------------------------------------------------
  205. Fill color and shading parameters.  Description:
  206.      "f" red green blue Kd Ks Shine T index_of_refraction
  207.  
  208. Format:
  209.     f %g %g %g %g %g %g %g %g
  210.  
  211.     RGB is in terms of 0.0 to 1.0.
  212.  
  213.     Kd is the diffuse component, Ks the specular, Shine is the Phong cosine
  214.     power for highlights, T is transmittance (fraction of light passed per
  215.     unit).  Usually, 0 <= Kd <= 1 and 0 <= Ks <= 1, though it is not required
  216.     that Kd + Ks == 1.  Note that transmitting objects ( T > 0 ) are considered
  217.     to have two sides for algorithms that need these (normally objects have
  218.     one side).
  219.  
  220.     The fill color is used to color the objects following it until a new color
  221.     is assigned.
  222. ----------------------------------------------------------------------*/
  223. static void
  224. do_fill(fp)
  225. FILE *fp;
  226. {
  227.     float    r, g, b, ka, kd, ks, shine, phong_pow, ang, t, ior;
  228.     COORD3 acolor;
  229.  
  230.    if (fscanf(fp, "%f %f %f",&r, &g, &b) != 3) {
  231.     show_error("fill color syntax error");
  232.     exit(1);
  233.     }
  234.     SET_COORD3(acolor,r,g,b);
  235.  
  236.     if (fscanf(fp, "%f %f %f %f %f", &kd, &ks, &phong_pow, &t, &ior) != 5) {
  237.         show_error("fill material syntax error");
  238.         exit(1);
  239.     }
  240.  
  241.     /* ooh yuck, some parms not input in NFF, so I hard-coded them for now [esp] */
  242.     ka = 0.1;
  243.     shine = 0.5;
  244.     /* convert phong_pow back into phong hilite angle. */
  245.     /* reciprocal of formula in libprm.c, lib_output_color() */
  246.     ang = (180.0/(2.0*PI)) * acos( exp((-log(2.0))/phong_pow) );
  247.     lib_output_color(NULL, acolor, ka, kd, ks, shine, ang, t, ior);
  248.  
  249. }
  250.  
  251.  
  252. /*----------------------------------------------------------------------
  253. Cylinder or cone.  A cylinder is defined as having a radius and an axis
  254.     defined by two points, which also define the top and bottom edge of the
  255.     cylinder.  A cone is defined similarly, the difference being that the apex
  256.     and base radii are different.  The apex radius is defined as being smaller
  257.     than the base radius.  Note that the surface exists without endcaps.  The
  258.     cone or cylinder description:
  259.  
  260.     "c"
  261.     base.x base.y base.z base_radius
  262.     apex.x apex.y apex.z apex_radius
  263.  
  264. Format:
  265.     c
  266.     %g %g %g %g
  267.     %g %g %g %g
  268.  
  269.     A negative value for both radii means that only the inside of the object is
  270.     visible (objects are normally considered one sided, with the outside
  271.     visible).  Note that the base and apex cannot be coincident for a cylinder
  272.     or cone.
  273. ----------------------------------------------------------------------*/
  274. static void
  275. do_cone(fp)
  276. FILE *fp;
  277. {
  278.     COORD4    base_pt;
  279.     COORD4    apex_pt;
  280.     float    x0, y0, z0, x1, y1, z1, r0, r1;
  281.  
  282.     if (fscanf(fp, " %f %f %f %f %f %f %f %f", &x0, &y0, &z0, &r0,
  283.             &x1, &y1, &z1, &r1) != 8) {
  284.         show_error("cylinder or cone syntax error");
  285.         exit(1);
  286.     }
  287.     if ( r0 < 0.0) {
  288.         r0 = -r0;
  289.         r1 = -r1;
  290.     }
  291.     SET_COORD4(base_pt,x0,y0,z0,r0);
  292.     SET_COORD4(apex_pt,x1,y1,z1,r1);
  293.  
  294.     lib_output_cylcone (base_pt, apex_pt, output_format);
  295. }
  296.  
  297.  
  298. /*----------------------------------------------------------------------
  299. Sphere.  A sphere is defined by a radius and center position:
  300.     "s" center.x center.y center.z radius
  301.  
  302. Format:
  303.     s %g %g %g %g
  304.  
  305.     If the radius is negative, then only the sphere's inside is visible
  306.     (objects are normally considered one sided, with the outside visible).
  307. ----------------------------------------------------------------------*/
  308. static void
  309. do_sphere(fp)
  310. FILE *fp;
  311. {
  312.     float    x, y, z, r;
  313.     COORD4    center_pt;
  314.  
  315.     if (fscanf(fp, "%f %f %f %f", &x, &y, &z, &r) != 4) {
  316.         show_error("sphere syntax error");
  317.         exit(1);
  318.     }
  319.  
  320.     SET_COORD4(center_pt,x,y,z,r);
  321.  
  322.     lib_output_sphere(center_pt, output_format);
  323. }
  324.  
  325.  
  326. /*----------------------------------------------------------------------
  327. Polygon.  A polygon is defined by a set of vertices.  With these databases,
  328.     a polygon is defined to have all points coplanar.  A polygon has only
  329.     one side, with the order of the vertices being counterclockwise as you
  330.     face the polygon (right-handed coordinate system).  The first two edges
  331.     must form a non-zero convex angle, so that the normal and side visibility
  332.     can be determined.  Description:
  333.  
  334.     "p" total_vertices
  335.     vert1.x vert1.y vert1.z
  336.     [etc. for total_vertices vertices]
  337.  
  338. Format:
  339.     p %d
  340.     [ %g %g %g ] <-- for total_vertices vertices
  341. ----------------------------------------------------------------------
  342. Polygonal patch.  A patch is defined by a set of vertices and their normals.
  343.     With these databases, a patch is defined to have all points coplanar.
  344.     A patch has only one side, with the order of the vertices being
  345.     counterclockwise as you face the patch (right-handed coordinate system).
  346.     The first two edges must form a non-zero convex angle, so that the normal
  347.     and side visibility can be determined.  Description:
  348.  
  349.     "pp" total_vertices
  350.     vert1.x vert1.y vert1.z norm1.x norm1.y norm1.z
  351.     [etc. for total_vertices vertices]
  352.  
  353. Format:
  354.     pp %d
  355.     [ %g %g %g %g %g %g ] <-- for total_vertices vertices
  356. ----------------------------------------------------------------------*/
  357. static void
  358. do_poly(fp)
  359. FILE *fp;
  360. {
  361.     int    ispatch;
  362.     int    nverts;
  363.     int    vertcount;
  364.     COORD3 *verts;
  365.     COORD3 *norms;
  366.     float    x, y, z;
  367.  
  368.     ispatch = getc(fp);
  369.     if (ispatch != 'p') {
  370.         ungetc(ispatch, fp);
  371.         ispatch = 0;
  372.     }
  373.  
  374.     if (fscanf(fp, "%d", &nverts) != 1)
  375.         goto fmterr;
  376.  
  377.     verts = (COORD3*)malloc(nverts*sizeof(COORD3));
  378.     if (verts == NULL)
  379.         goto memerr;
  380.  
  381.     if (ispatch) {
  382.         norms = (COORD3*)malloc(nverts*sizeof(COORD3));
  383.         if (norms == NULL)
  384.             goto memerr;
  385.     }
  386.  
  387.     /* read all the vertices into temp array */
  388.     for (vertcount = 0; vertcount < nverts; vertcount++) {
  389.         if (fscanf(fp, " %f %f %f", &x, &y, &z) != 3)
  390.             goto fmterr;
  391.         SET_COORD3(verts[vertcount],x,y,z);
  392.  
  393.         if (ispatch) {
  394.             if (fscanf(fp, " %f %f %f", &x, &y, &z) != 3)
  395.                 goto fmterr;
  396.             SET_COORD3(norms[vertcount],x,y,z);
  397.         }
  398.     }
  399.  
  400.     /* write output */
  401.     if (ispatch)
  402.         lib_output_polypatch(nverts, verts, norms);
  403.     else
  404.         lib_output_polygon(nverts, verts);
  405.  
  406.     free(verts);
  407.     if (ispatch)
  408.         free(norms);
  409.  
  410.     return;
  411. fmterr:
  412.     show_error("polygon or patch syntax error");
  413.     exit(1);
  414. memerr:
  415.     show_error("can't allocate memory for polygon or patch");
  416.     exit(1);
  417. }
  418.  
  419.  
  420. /*----------------------------------------------------------------------
  421. ----------------------------------------------------------------------*/
  422. static void
  423. parse_nff(fp)
  424. FILE *fp;
  425. {
  426.     int        c;
  427.     char    errstr[80];
  428.  
  429.     while ( (c = getc(fp)) != EOF )
  430.         switch (c) {
  431.         case ' ':            /* white space */
  432.         case '\t':
  433.         case '\n':
  434.         case '\f':
  435.         case '\r':
  436.             continue;
  437.         case '#':            /* comment */
  438.             do_comment(fp);
  439.             break;
  440.         case 'v':            /* view point */
  441.             do_view(fp);
  442.             break;
  443.         case 'l':            /* light source */
  444.             do_light(fp);
  445.             break;
  446.         case 'b':            /* background color */
  447.             do_background(fp);
  448.             break;
  449.         case 'f':            /* fill material */
  450.             do_fill(fp);
  451.             break;
  452.         case 'c':            /* cylinder or cone */
  453.             do_cone(fp);
  454.             break;
  455.         case 's':            /* sphere */
  456.             do_sphere(fp);
  457.             break;
  458.         case 'p':            /* polygon or patch */
  459.             do_poly(fp);
  460.             break;
  461.         default:            /* unknown */
  462.             show_error("unknown NFF primitive code");
  463.             exit(1);
  464.         }
  465. } /* parse_nff */
  466.  
  467.  
  468. /*----------------------------------------------------------------------
  469. ----------------------------------------------------------------------*/
  470. int
  471. main(argc,argv)
  472.     int argc ;
  473.     char *argv[] ;
  474. {
  475.     char file_name[64];
  476.     FILE *fp;
  477.  
  478.     PLATFORM_INIT(SPD_READNFF);
  479.  
  480.     /* Start by defining which raytracer we will be using */
  481.     if ( lib_read_get_opts( argc, argv,
  482.             &raytracer_format, &output_format, file_name ) ) {
  483.     return EXIT_FAIL;
  484.     }
  485.  
  486.     if ( lib_open( raytracer_format, "ReadNFF.out" ) ) {
  487.     return EXIT_FAIL;
  488.     }
  489.  
  490.     fp = fopen(file_name, "r");
  491.     if (fp == NULL) {
  492.     fprintf(stderr, "Cannot open nff file: '%s'\n", file_name);
  493.     return EXIT_FAIL;
  494.     }
  495.  
  496.     lib_set_polygonalization(3, 3);
  497.  
  498.     parse_nff(fp);
  499.  
  500.     fclose(fp);
  501.  
  502.     lib_close();
  503.  
  504.     PLATFORM_SHUTDOWN();
  505.     return EXIT_SUCCESS;
  506. }
  507.